package com.orange.quartz.context;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.log4j.Logger;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;

import com.orange.expireFile.entity.ExpireFile;
import com.orange.quartz.job.QuartzJobFactory;
import com.orange.quartz.schedule.ScheduleJob;

/**
 * @author: HH
 * @Description: Job管理
 * @date 2017年9月18日 下午4:11:47
 */
public class QuartzJobContext {

	private static final Logger logger = Logger.getLogger(QuartzJobContext.class);

	private static SchedulerFactory gSchedulerFactory = new StdSchedulerFactory();

	private static Scheduler scheduler;

	static {
		try {
			if (scheduler == null) {
				logger.info("scheduler == null");
				scheduler = gSchedulerFactory.getScheduler();
			}
		} catch (SchedulerException e) {
			e.printStackTrace();
		}
	}

	// 设置任务map，key为组名+任务名
	private static Map<String, ScheduleJob> jobMap = new HashMap<String, ScheduleJob>();// 所有任务
	private static Map<String, ScheduleJob> removeJobMap = new HashMap<String, ScheduleJob>();// 删除任务
	private static Map<String, ScheduleJob> disableJobMap = new HashMap<String, ScheduleJob>();// 禁用任务

	/**
	 * @Description: 初始化JobMap
	 * @param expireFileMap
	 */
	public static void initScheduleJobMap(Map<String, ExpireFile> expireFileMap) {

		jobMap.clear();
		removeJobMap.clear();
		disableJobMap.clear();

		int jobId = 100;
		for (Entry<String, ExpireFile> entry : expireFileMap.entrySet()) {
			ExpireFile expireFile = entry.getValue();
			ScheduleJob job = new ScheduleJob();
			job.setJobId(jobId + "");
			job.setJobName(entry.getKey());
			job.setTriggerName(expireFile.getExpireFileDes());
			job.setJobStatus(expireFile.getExpireFileSchedulerStatus() + "");
			job.setCronExpression(expireFile.getExpireFileScheduler());
			job.setDesc(expireFile.getExpireFileDes());
			logger.info(job.toString());
			addJob(job);
			if (expireFile.getExpireFileSchedulerStatus() == 0) {
				disableJobMap.put(job.getJobGroup() + "_" + job.getJobName(), job);
			} else if (expireFile.getExpireFileSchedulerStatus() == 2) {
				removeJobMap.put(job.getJobGroup() + "_" + job.getJobName(), job);
			}
			jobId++;
		}
	}

	/**
	 * @Description: 添加任务
	 * @param scheduleJob
	 */
	public static void addJob(ScheduleJob scheduleJob) {
		jobMap.put(scheduleJob.getJobGroup() + "_" + scheduleJob.getJobName(), scheduleJob);
	}

	/**
	 * @Description: 获取jobMap
	 * @return
	 */
	public static Map<String, ScheduleJob> getAllMapJob() {
		return jobMap;
	}

	/**
	 * @Description: 根据jobMap获取jobList
	 * @return
	 */
	public static List<ScheduleJob> getAllJob(Map<String, ScheduleJob> jobMap) {
		List<ScheduleJob> listScheduleJob = new ArrayList<ScheduleJob>();
		for (String s : jobMap.keySet()) {
			listScheduleJob.add(jobMap.get(s));
		}
		return listScheduleJob;
	}

	/**
	 * @Description: 调度所有任务 
	 * @throws SchedulerException
	 */
	public static void setAllJobs() throws SchedulerException {
		setJobs();
		startJobs();
		setDisableJob();
		setRemoveJob();
	}
	
	/**
	 * @Description: 根据jobList添加任务
	 * @throws SchedulerException
	 */
	public static void setJobs() throws SchedulerException {
		List<ScheduleJob> jobList = getAllJob(jobMap);
		for (ScheduleJob job : jobList) {
			TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobName(), job.getJobGroup());
			// 获取trigger，即在spring配置文件中定义的 bean id="myTrigger"
			CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
			// 不存在，创建一个
			if (null == trigger) {
				JobDetail jobDetail = JobBuilder.newJob(QuartzJobFactory.class)
						.withIdentity(job.getJobName(), job.getJobGroup()).build();
				jobDetail.getJobDataMap().put("scheduleJob", job);
				// 表达式调度构建器
				CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
				// 按新的cronExpression表达式构建一个新的trigger
				trigger = TriggerBuilder.newTrigger().withIdentity(job.getJobName(), job.getJobGroup())
						.withSchedule(scheduleBuilder).build();
				scheduler.scheduleJob(jobDetail, trigger);
			} else {
				// Trigger已存在，那么更新相应的定时设置
				// 表达式调度构建器
				CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
				// 按新的cronExpression表达式重新构建trigger
				trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
				// 按新的trigger重新设置job执行
				scheduler.rescheduleJob(triggerKey, trigger);
			}
		}
	}

	/**
	 * @Description: 根据disableJobMap禁用所有job
	 */
	public static void setDisableJob() {
		List<ScheduleJob> jobList = getAllJob(disableJobMap);
		for (ScheduleJob scheduleJob : jobList) {
			disableJob(scheduleJob);
		}
	}

	/**
	 * @Description: 根据removeJobMap移除所有job
	 * @param jobList
	 */
	public static void setRemoveJob() {
		List<ScheduleJob> jobList = getAllJob(removeJobMap);
		for (ScheduleJob scheduleJob : jobList) {
			try {
				removeJob(scheduleJob);
			} catch (SchedulerException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * @Description: 删除Job
	 * @param job
	 * @throws SchedulerException
	 */
	public static void removeJob(ScheduleJob job) throws SchedulerException {
		try {
			// 获取jobKey
			JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());
			disableJob(job);
			scheduler.deleteJob(jobKey);// 删除任务
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * @Description: 禁用Job
	 * @param job
	 */
	public static void disableJob(ScheduleJob job) {
		try {
			// 获取triggerKey
			TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobName(), job.getJobGroup());
			scheduler.pauseTrigger(triggerKey);// 停止触发器
			scheduler.unscheduleJob(triggerKey);// 移除触发器
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * @Description: 启动所有定时任务
	 */
	public static void startJobs() {
		try {
			scheduler.start();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * @Description: 关闭所有定时任务
	 */
	public static void shutdownJobs() {
		try {
			if (!scheduler.isShutdown()) {
				scheduler.shutdown();
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * @Description: 获取JobDetail
	 * @param job
	 * @param j
	 * @return
	 */
	public static JobDetail getJobDetatil(ScheduleJob job, Class<? extends Job> j) {
		// 获取jobKey
		JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());
		JobDetail jobDetail = JobBuilder.newJob(j).withIdentity(jobKey).build();
		jobDetail.getJobDataMap().put("scheduleJob", job);
		return jobDetail;
	}

}
